/*
 * Copyright 2022 the original author or authors.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * https://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.openrewrite.maven;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openrewrite.DocumentExample;
import org.openrewrite.Issue;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.test.SourceSpec;

import static java.util.Collections.singletonList;
import static org.openrewrite.java.Assertions.mavenProject;
import static org.openrewrite.maven.Assertions.pomXml;

class RemoveRedundantDependencyVersionsTest implements RewriteTest {

    @Override
    public void defaults(RecipeSpec spec) {
        spec.recipe(new RemoveRedundantDependencyVersions(null, null, null, null));
    }

    @DocumentExample
    @Test
    void matchesOwnDmThenRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>com.google.guava</groupId>
                          <artifactId>guava</artifactId>
                          <version>30.0-jre</version>
                      </dependency>
                  </dependencies>
              </project>
              """,
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>com.google.guava</groupId>
                          <artifactId>guava</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @Test
    void givenScopeIsDefinedWhenVersionMatchesParentDmForDifferentScopeThenStillRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                              <scope>test</scope>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>30.0-jre</version>
                                <scope>compile</scope>
                            </dependency>
                        </dependencies>
                    </project>
                """,
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <scope>compile</scope>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void givenScopeIsDefinedWhenVersionMatchesParentDmForSameScopeAndCompileAndEmptyThenRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                              <scope>compile</scope>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>30.0-jre</version>
                            </dependency>
                        </dependencies>
                    </project>
                """,
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void givenScopeIsDefinedWhenVersionMatchesParentDmForSameScopeAndEmptyAndCompileThenRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>30.0-jre</version>
                                <scope>compile</scope>
                            </dependency>
                        </dependencies>
                    </project>
                """,
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <scope>compile</scope>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void givenScopeIsDefinedWhenVersionMatchesParentDmForSameScopeThenRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                              <scope>test</scope>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>30.0-jre</version>
                                <scope>test</scope>
                            </dependency>
                        </dependencies>
                    </project>
                """,
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <scope>test</scope>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void matchesParentDmThenRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>30.0-jre</version>
                            </dependency>
                        </dependencies>
                    </project>
                """,
              """
                <project>
                    <parent>
                        <groupId>org.example</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0-SNAPSHOT</version>
                    </parent>
                    <artifactId>child</artifactId>
                    <dependencies>
                        <dependency>
                            <groupId>com.google.guava</groupId>
                            <artifactId>guava</artifactId>
                        </dependency>
                    </dependencies>
                </project>
                """
            )
          )
        );
    }

    @Test
    void givenVersionMatchesParentDmWhenOwnDmIsDifferentThenKeepIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencyManagement>
                            <dependencies>
                                <dependency>
                                    <groupId>com.google.guava</groupId>
                                    <artifactId>guava</artifactId>
                                    <version>29.0-jre</version>
                                </dependency>
                            </dependencies>
                        </dependencyManagement>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>30.0-jre</version>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void whenNoParentOrOwnDmThenKeepIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>com.mycompany</groupId>
                  <artifactId>myApiApp</artifactId>
                  <version>1.0.0</version>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <modelVersion>4.0.0</modelVersion>
                        <groupId>com.mycompany</groupId>
                        <artifactId>mySharedLibrary</artifactId>
                        <version>1.0.0</version>
                        <parent>
                            <groupId>com.mycompany</groupId>
                            <artifactId>myApiApp</artifactId>
                            <version>1.0.0</version>
                        </parent>
                
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>30.0-jre</version>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void whenNoVersionDefinedThenMakeNoChanges() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>com.mycompany</groupId>
                  <artifactId>myApiApp</artifactId>
                  <version>1.0.0</version>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <modelVersion>4.0.0</modelVersion>
                        <groupId>com.mycompany</groupId>
                        <artifactId>mySharedLibrary</artifactId>
                        <version>1.0.0</version>
                        <parent>
                            <groupId>com.mycompany</groupId>
                            <artifactId>myApiApp</artifactId>
                            <version>1.0.0</version>
                        </parent>
                
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void doesntMatchParentDmOrOwnDmThenKeepIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>com.mycompany</groupId>
                  <artifactId>myApiApp</artifactId>
                  <version>1.0.0</version>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>30.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <groupId>com.mycompany</groupId>
                        <artifactId>mySharedLibrary</artifactId>
                        <version>1.0.0</version>
                        <parent>
                            <groupId>com.mycompany</groupId>
                            <artifactId>myApiApp</artifactId>
                            <version>1.0.0</version>
                        </parent>
                        <dependencyManagement>
                            <dependencies>
                                <dependency>
                                    <groupId>com.google.guava</groupId>
                                    <artifactId>guava</artifactId>
                                    <version>29.0-jre</version>
                                </dependency>
                            </dependencies>
                        </dependencyManagement>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                                <version>28.0-jre</version>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Test
    void givenNestedPomsWhenVersionMatchesImmediateParentThenRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>29.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <modules>
                            <module>child-2</module>
                        </modules>
                        <dependencyManagement>
                            <dependencies>
                                <dependency>
                                    <groupId>com.google.guava</groupId>
                                    <artifactId>guava</artifactId>
                                    <version>30.0-jre</version>
                                </dependency>
                            </dependencies>
                        </dependencyManagement>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                            </dependency>
                        </dependencies>
                    </project>
                """
            ),
            mavenProject("child-2",
              pomXml(
                """
                      <project>
                          <parent>
                              <groupId>org.example</groupId>
                              <artifactId>child</artifactId>
                              <version>1.0-SNAPSHOT</version>
                          </parent>
                          <artifactId>child-2</artifactId>
                          <dependencies>
                              <dependency>
                                  <groupId>com.google.guava</groupId>
                                  <artifactId>guava</artifactId>
                                  <version>30.0-jre</version>
                              </dependency>
                          </dependencies>
                      </project>
                  """,
                """
                  <project>
                      <parent>
                          <groupId>org.example</groupId>
                          <artifactId>child</artifactId>
                          <version>1.0-SNAPSHOT</version>
                      </parent>
                      <artifactId>child-2</artifactId>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                          </dependency>
                      </dependencies>
                  </project>
                  """
              )
            )
          )
        );
    }

    @Test
    void givenNestedPomsWhenVersionMatchesTopLevelParentThenRemoveIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>29.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <modules>
                            <module>child-2</module>
                        </modules>
                        <dependencies>
                            <dependency>
                                <groupId>com.google.guava</groupId>
                                <artifactId>guava</artifactId>
                            </dependency>
                        </dependencies>
                    </project>
                """
            ),
            mavenProject("child-2",
              pomXml(
                """
                      <project>
                          <parent>
                              <groupId>org.example</groupId>
                              <artifactId>child</artifactId>
                              <version>1.0-SNAPSHOT</version>
                          </parent>
                          <artifactId>child-2</artifactId>
                          <dependencies>
                              <dependency>
                                  <groupId>com.google.guava</groupId>
                                  <artifactId>guava</artifactId>
                                  <version>29.0-jre</version>
                              </dependency>
                          </dependencies>
                      </project>
                  """,
                """
                  <project>
                      <parent>
                          <groupId>org.example</groupId>
                          <artifactId>child</artifactId>
                          <version>1.0-SNAPSHOT</version>
                      </parent>
                      <artifactId>child-2</artifactId>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                          </dependency>
                      </dependencies>
                  </project>
                  """
              )
            )
          )
        );
    }

    @Test
    void givenNestedPomsWhenVersionMatchesTopLevelParentAndDoesntMatchFirstLevelParentThenKeepIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>29.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <modules>
                            <module>child-module-2</module>
                        </modules>
                        <dependencyManagement>
                            <dependencies>
                                <dependency>
                                    <groupId>com.google.guava</groupId>
                                    <artifactId>guava</artifactId>
                                    <version>30.0-jre</version>
                                </dependency>
                            </dependencies>
                        </dependencyManagement>
                    </project>
                """
            ),
            mavenProject("child-2",
              pomXml(
                """
                      <project>
                          <parent>
                              <groupId>org.example</groupId>
                              <artifactId>child</artifactId>
                              <version>1.0-SNAPSHOT</version>
                          </parent>
                          <artifactId>child-module-2</artifactId>
                          <dependencies>
                              <dependency>
                                  <groupId>com.google.guava</groupId>
                                  <artifactId>guava</artifactId>
                                  <version>29.0-jre</version>
                              </dependency>
                          </dependencies>
                      </project>
                  """
              )
            )
          )
        );
    }

    @Test
    void givenNestedPomsWhenVersionDoesntMatchAnyDmThenKeepIt() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>com.google.guava</groupId>
                              <artifactId>guava</artifactId>
                              <version>29.0-jre</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <modules>
                            <module>child-2</module>
                        </modules>
                        <dependencyManagement>
                            <dependencies>
                                <dependency>
                                    <groupId>com.google.guava</groupId>
                                    <artifactId>guava</artifactId>
                                    <version>28.0-jre</version>
                                </dependency>
                            </dependencies>
                        </dependencyManagement>
                    </project>
                """
            ),
            mavenProject("child-2",
              pomXml(
                """
                      <project>
                          <parent>
                              <groupId>org.example</groupId>
                              <artifactId>child</artifactId>
                              <version>1.0-SNAPSHOT</version>
                          </parent>
                          <artifactId>child-2</artifactId>
                          <dependencies>
                              <dependency>
                                  <groupId>com.google.guava</groupId>
                                  <artifactId>guava</artifactId>
                                  <version>30.0-jre</version>
                              </dependency>
                          </dependencies>
                      </project>
                  """
              )
            )
          )
        );
    }

    @Test
    void except() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE,
            singletonList("org.junit.jupiter:junit-jupiter-api"))),
          pomXml(
            """
              <project>
                  <parent>
                      <groupId>org.junit</groupId>
                      <artifactId>junit-bom</artifactId>
                      <version>5.8.0</version>
                  </parent>
                  <artifactId>child</artifactId>
                  <dependencies>
                      <dependency>
                          <groupId>org.junit.jupiter</groupId>
                          <artifactId>junit-jupiter-api</artifactId>
                          <version>5.8.0</version>
                      </dependency>
                      <dependency>
                          <groupId>org.junit.jupiter</groupId>
                          <artifactId>junit-jupiter-params</artifactId>
                          <version>5.8.0</version>
                      </dependency>
                  </dependencies>
              </project>
              """,
            """
              <project>
                  <parent>
                      <groupId>org.junit</groupId>
                      <artifactId>junit-bom</artifactId>
                      <version>5.8.0</version>
                  </parent>
                  <artifactId>child</artifactId>
                  <dependencies>
                      <dependency>
                          <groupId>org.junit.jupiter</groupId>
                          <artifactId>junit-jupiter-api</artifactId>
                          <version>5.8.0</version>
                      </dependency>
                      <dependency>
                          <groupId>org.junit.jupiter</groupId>
                          <artifactId>junit-jupiter-params</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @Issue("https://github.com/openrewrite/rewrite/issues/3268")
    @Test
    void unmanagedDependency() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <dependencies>
                      <dependency>
                          <groupId>com.google.guava</groupId>
                          <artifactId>guava</artifactId>
                          <version>30.0-jre</version>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @Issue("https://github.com/openrewrite/rewrite/issues/3268")
    @Test
    void unmanagedDependencyAnyMatch() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.ANY, null)),
          pomXml(
            """
              <project>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <dependencies>
                      <dependency>
                          <groupId>com.google.guava</groupId>
                          <artifactId>guava</artifactId>
                          <version>30.0-jre</version>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @Test
    void removeRedundantVersionsFromManagedPlugins() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <version>4.9.10</version>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                              <version>4.9.10</version>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """,
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <version>4.9.10</version>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """
          )
        );
    }

    @Test
    void removeRedundantVersionsFromManagedButNonInheritedPlugins() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <version>4.9.10</version>
                                  <inherited>false</inherited>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                              <version>4.9.10</version>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """,
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <version>4.9.10</version>
                                  <inherited>false</inherited>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """
          )
        );
    }

    @Issue("https://github.com/openrewrite/rewrite/issues/3932")
    @Test
    void removeRedundantVersionsFromPluginsManagedByParent() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                              <version>4.9.10</version>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """,
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """
          )
        );
    }

    @Test
    void removeRedundantVersionsFromPluginsManagedByParentNotSpecifyingGroupId() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <artifactId>maven-resources-plugin</artifactId>
                                  <configuration><whatever/></configuration>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                  </build>
              </project>
              """,
            SourceSpec::skip),
          mavenProject("child", pomXml(
              """
                <project>
                    <modelVersion>4.0.0</modelVersion>
                    <parent>
                        <groupId>org.sample</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0.0</version>
                        <relativePath/>
                    </parent>
                    <artifactId>sample</artifactId>
                    <build>
                        <plugins>
                            <plugin>
                                <artifactId>maven-resources-plugin</artifactId>
                                <version>3.0.0</version>
                                <configuration>
                                    <something-else/>
                                </configuration>
                            </plugin>
                        </plugins>
                    </build>
                </project>
                """,
              """
                <project>
                    <modelVersion>4.0.0</modelVersion>
                    <parent>
                        <groupId>org.sample</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0.0</version>
                        <relativePath/>
                    </parent>
                    <artifactId>sample</artifactId>
                    <build>
                        <plugins>
                            <plugin>
                                <artifactId>maven-resources-plugin</artifactId>
                                <configuration>
                                    <something-else/>
                                </configuration>
                            </plugin>
                        </plugins>
                    </build>
                </project>
                """
            )
          )
        );
    }

    @Test
    void removeRedundantDmVersionsFromPluginsManagedByParentNotSpecifyingGroupId() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <artifactId>maven-resources-plugin</artifactId>
                                  <configuration><whatever/></configuration>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                  </build>
              </project>
              """,
            SourceSpec::skip),
          mavenProject("child", pomXml(
              """
                <project>
                    <modelVersion>4.0.0</modelVersion>
                    <parent>
                        <groupId>org.sample</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0.0</version>
                        <relativePath/>
                    </parent>
                    <artifactId>sample</artifactId>
                    <build>
                        <pluginManagement>
                            <plugins>
                                <plugin>
                                    <artifactId>maven-resources-plugin</artifactId>
                                    <version>3.0.0</version>
                                    <configuration>
                                        <something-else/>
                                    </configuration>
                                </plugin>
                            </plugins>
                        </pluginManagement>
                    </build>
                </project>
                """,
              """
                <project>
                    <modelVersion>4.0.0</modelVersion>
                    <parent>
                        <groupId>org.sample</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0.0</version>
                        <relativePath/>
                    </parent>
                    <artifactId>sample</artifactId>
                    <build>
                        <pluginManagement>
                            <plugins>
                                <plugin>
                                    <artifactId>maven-resources-plugin</artifactId>
                                    <configuration>
                                        <something-else/>
                                    </configuration>
                                </plugin>
                            </plugins>
                        </pluginManagement>
                    </build>
                </project>
                """
            )
          )
        );
    }

    @Test
    void keepPluginIfParentInheritanceDisabled() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child-with-pluginManagement</module>
                      <module>child-with-plugin-execution</module>
                  </modules>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <version>4.9.10</version>
                                  <inherited>false</inherited>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                  </build>
              </project>
              """
          ),
          mavenProject("child-with-pluginManagement",
            pomXml(
              """
                <project>
                    <parent>
                        <groupId>org.example</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0-SNAPSHOT</version>
                    </parent>
                    <artifactId>child-with-pluginManagement</artifactId>
                    <build>
                        <pluginManagement>
                            <plugins>
                                <plugin>
                                    <groupId>pl.project13.maven</groupId>
                                    <artifactId>git-commit-id-plugin</artifactId>
                                    <version>4.9.10</version>
                                </plugin>
                            </plugins>
                        </pluginManagement>
                    </build>
                </project>
                """
            )
          ),
          mavenProject("child-with-plugin-execution",
            pomXml(
              """
                <project>
                    <parent>
                        <groupId>org.example</groupId>
                        <artifactId>parent</artifactId>
                        <version>1.0-SNAPSHOT</version>
                    </parent>
                    <artifactId>child-with-plugin-execution</artifactId>
                    <build>
                        <plugins>
                            <plugin>
                                <groupId>pl.project13.maven</groupId>
                                <artifactId>git-commit-id-plugin</artifactId>
                                <version>4.9.10</version>
                            </plugin>
                        </plugins>
                    </build>
                </project>
                """
            )
          )
        );
    }

    @Test
    void removeRedundantManagedVersionFromPluginsManagedByParentAndKeepOtherElements() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <version>4.9.10</version>
                                  <configuration><whatever /></configuration>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                  </build>
              </project>
              """,
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <configuration><whatever /></configuration>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                  </build>
              </project>
              """
          )
        );
    }

    @Test
    void removeRedundantManagedPluginWhenPluginManagedByParentAndNoOtherElement() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <pluginManagement>
                          <plugins>
                              <plugin>
                                  <groupId>pl.project13.maven</groupId>
                                  <artifactId>git-commit-id-plugin</artifactId>
                                  <version>4.9.10</version>
                              </plugin>
                          </plugins>
                      </pluginManagement>
                  </build>
              </project>
              """,
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                  </build>
              </project>
              """
          )
        );
    }

    @Issue("https://github.com/openrewrite/rewrite/issues/3932")
    @Test
    void noChangesIfManagedPluginVersionDoesNotMatch() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.EQ, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                              <version>4.9.9</version>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """
          )
        );
    }

    @Test
    void doesNotDowngradeVersion() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <groupId>org.sample</groupId>
                  <artifactId>sample</artifactId>
                  <version>1.0.0</version>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.7.18</version>
                      <relativePath/>
                  </parent>
                  <build>
                      <plugins>
                          <plugin>
                              <groupId>pl.project13.maven</groupId>
                              <artifactId>git-commit-id-plugin</artifactId>
                              <!-- version in pom is 4.9.10, pin should be kept-->
                              <version>4.9.11</version>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """
          )
        );
    }

    @Test
    void allowUpgradeOfManagedVersion() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.3.12.RELEASE</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-web</artifactId>
                              <version>2.2.13.RELEASE</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """,
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.3.12.RELEASE</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @Test
    void pluginPropertySubstitution() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.3.0.RELEASE</version>
                      <relativePath/>
                  </parent>
              
                  <groupId>com.example</groupId>
                  <artifactId>test</artifactId>
                  <version>1.0.0-SNAPSHOT</version>
              
                  <modelVersion>4.0.0</modelVersion>
                  <build>
                      <plugins>
                          <plugin>
                              <artifactId>kotlin-maven-plugin</artifactId>
                              <groupId>org.jetbrains.kotlin</groupId>
                              <version>${kotlin.version}</version>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """,
            """
              <project>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.3.0.RELEASE</version>
                      <relativePath/>
                  </parent>
              
                  <groupId>com.example</groupId>
                  <artifactId>test</artifactId>
                  <version>1.0.0-SNAPSHOT</version>
              
                  <modelVersion>4.0.0</modelVersion>
                  <build>
                      <plugins>
                          <plugin>
                              <artifactId>kotlin-maven-plugin</artifactId>
                              <groupId>org.jetbrains.kotlin</groupId>
                          </plugin>
                      </plugins>
                  </build>
              </project>
              """
          )
        );
    }

    @Test
    void dependencyPropertySubstitution() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.5.4</version>
                      <relativePath/>
                  </parent>
              
                  <groupId>com.example</groupId>
                  <artifactId>test</artifactId>
                  <version>1.0.0-SNAPSHOT</version>
              
                  <modelVersion>4.0.0</modelVersion>
              
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework</groupId>
                          <artifactId>spring-web</artifactId>
                          <version>${spring-framework.version}</version>
                      </dependency>
                  </dependencies>
              </project>
              """,
            """
              <project>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.5.4</version>
                      <relativePath/>
                  </parent>
              
                  <groupId>com.example</groupId>
                  <artifactId>test</artifactId>
                  <version>1.0.0-SNAPSHOT</version>
              
                  <modelVersion>4.0.0</modelVersion>
              
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework</groupId>
                          <artifactId>spring-web</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @CsvSource({"GT,2.5.0", "GTE,2.5.0", "ANY,2.5.0", "EQ,2.5.1", "LTE,2.5.1", "GTE,2.5.1", "ANY,2.5.1", "LT,2.5.2", "LTE,2.5.2", "ANY,2.5.2"})
    @ParameterizedTest
    void onlyIfManagedVersionIs_removals(String comparator, String projectVersion) {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.valueOf(comparator), null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.5.1</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                          <version>%s</version>
                      </dependency>
                  </dependencies>
              </project>
              """.formatted(projectVersion),
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.5.1</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @CsvSource({"LT,2.5.0", "LTE,2.5.0", "EQ,2.5.0", "LT,2.5.1", "GT,2.5.1", "GT,2.5.2", "GTE,2.5.2", "EQ,2.5.2"})
    @ParameterizedTest
    void onlyIfManagedVersionIs_nonremovals(String comparator, String projectVersion) {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.valueOf(comparator), null)),
          pomXml(
            //language=xml
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.5.1</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                          <version>%s</version>
                      </dependency>
                  </dependencies>
              </project>
              """.formatted(projectVersion)
          )
        );
    }

    @Test
    void keepVersionIfManagedIsNonExact() {
        rewriteRun(
          pomXml(
            """
              <project>
                  <groupId>org.example</groupId>
                  <artifactId>parent</artifactId>
                  <version>1.0-SNAPSHOT</version>
                  <modules>
                      <module>child</module>
                  </modules>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>org.springframework</groupId>
                              <artifactId>spring-web</artifactId>
                              <version>[5,6)</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
              </project>
              """
          ),
          mavenProject("child",
            pomXml(
              """
                    <project>
                        <parent>
                            <groupId>org.example</groupId>
                            <artifactId>parent</artifactId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <artifactId>child</artifactId>
                        <dependencies>
                            <dependency>
                                <groupId>org.springframework</groupId>
                                <artifactId>spring-web</artifactId>
                                <version>5.3.0</version>
                            </dependency>
                        </dependencies>
                    </project>
                """
            )
          )
        );
    }

    @Issue("https://github.com/openrewrite/rewrite/discussions/4386")
    @Test
    void dontOverrideDependencyConfigurations() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(null, null, RemoveRedundantDependencyVersions.Comparator.GTE, null)),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.3.12.RELEASE</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencyManagement>
                      <dependencies>
                          <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-web</artifactId>
                              <version>2.2.13.RELEASE</version>
                              <!-- This exclusion should be kept -->
                              <exclusions>
                                  <exclusion>
                                      <groupId>org.slf4j</groupId>
                                      <artifactId>slf4j-api</artifactId>
                                  </exclusion>
                              </exclusions>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }

    @Test
    void exceptManagedDependencyShouldNotBeRemoved() {
        rewriteRun(
          spec -> spec.recipe(new RemoveRedundantDependencyVersions(
            null, null, RemoveRedundantDependencyVersions.Comparator.GTE,
            singletonList("org.springframework.boot:spring-boot-starter-web"))),
          pomXml(
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.3.12.RELEASE</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencyManagement>
                      <dependencies>
                          <!-- This dependency is in except list and should not be removed -->
                          <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-web</artifactId>
                              <version>2.2.13.RELEASE</version>
                          </dependency>
                          <!-- This dependency is not in except list and should be removed -->
                          <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-test</artifactId>
                              <version>2.2.13.RELEASE</version>
                          </dependency>
                      </dependencies>
                  </dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-test</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """,
            """
              <project>
                  <modelVersion>4.0.0</modelVersion>
                  <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.3.12.RELEASE</version>
                  </parent>
                  <groupId>com.example</groupId>
                  <artifactId>acme</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
                  <dependencyManagement>
                      <dependencies>
                          <!-- This dependency is in except list and should not be removed -->
                          <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-web</artifactId>
                              <version>2.2.13.RELEASE</version>
                          </dependency>
                          <!-- This dependency is not in except list and should be removed -->
                      </dependencies>
                  </dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>
                      <dependency>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-test</artifactId>
                      </dependency>
                  </dependencies>
              </project>
              """
          )
        );
    }
}
